#ifndef TCPCLIENT_HPP
#define TCPCLIENT_HPP
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

#include <cstring>
#include <iostream>
#include <string>

class TcpClient {
 public:
  TcpClient(const std::string& ip, int16_t port)
      : sockfd_(-1), ip_(ip), port_(port) {}

  void Init() {
    // 创建TCP套接字
    sockfd_ = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd_ < 0) {
      printf("socket error , error message: %s\n", strerror(errno));
      exit(2);
    }
  }

  void Request() {
    std::string request;
    char buff[4096];

    while (true) {
      // 发起请求
      std::cout << "Please Enter# ";
      std::getline(std::cin, request);
      write(sockfd_, request.c_str(), request.size());

      // 接收响应
      int n = read(sockfd_, buff, sizeof(buff));
      if (n > 0) {
        buff[n] = 0;
        std::cout << buff << std::endl;
      } else if (n == 0) {
        std::cout << "Server exit...." << std::endl;
        break;
      } else {
        printf("Client read error, error message: %s\n", strerror(errno));
        break;
      }
    }
  }

  void Start() {
    // 对服务端发起连接 请求 以及接收服务端的响应

    // 发起连接
    struct sockaddr_in server;
    memset(&server, 0, sizeof(server));
    server.sin_family = AF_INET;
    inet_pton(AF_INET, ip_.c_str(), &(server.sin_addr));
    server.sin_port = htons(port_);
    socklen_t len = sizeof(server);

    if (connect(sockfd_, (sockaddr*)&server, len)) {
      printf("connect error , error message: %s\n", strerror(errno));
      exit(3);
    }

    Request();
  }

  ~TcpClient() {
    // 关闭无用的TCP套接字描述符
    if (sockfd_ != -1) {
      close(sockfd_);
      sockfd_ = -1;
    }
  }


 private:
  int sockfd_;      // 套接字描述符
  std::string ip_;  // 用户传递的IP地址
  int16_t port_;    // 用户传入的端口号
};
#endif